package com.xm.common;

import cn.hutool.core.thread.SyncFinisher;
import cn.hutool.core.thread.ThreadFactoryBuilder;
import com.xm.service.impl.BuyXmGoodServiceImpl;
import lombok.Builder;
import lombok.Getter;

import java.lang.reflect.Field;
import java.util.HashSet;
import java.util.Set;
import java.util.concurrent.*;

/**
 * @Author tianqin
 * @Date 2024/7/26 16:10
 * 自定义线程池
 */
public class ThreadPool {
    @Getter
    private static final ThreadPoolExecutor poolExecutor = new ThreadPoolExecutor(8, 16,
            60, TimeUnit.MINUTES,
            new ArrayBlockingQueue<>(5000),
            new ThreadFactoryBuilder().setNamePrefix("http-nio-7779-exec-tq").build(),
            new ThreadPool.DiscardPolicy());

    /**
     * 自定义线程池拒绝策略
     */
    private static class DiscardPolicy implements RejectedExecutionHandler {
        @Override
        public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {
            System.out.println("超过最大队列长度%s".formatted(r.toString()));
        }
    }

    /**
     * 自定义线程工作类
     * @param productId
     */
    @Builder
    public record ClockOrderTask(Long productId,Integer addressId,String bankCardNumber,String passCode) implements Callable<String> {
        @Override
        public String call() throws Exception {
            BuyXmGoodServiceImpl buyXmGoodService = new BuyXmGoodServiceImpl();
            return buyXmGoodService.clockXmOrder(productId,addressId,bankCardNumber,passCode);
        }
    }

    /**
     * 根据线程名称中断特定任务
     * @param threadNameContains 线程名称包含的字符串
     * @return 是否找到并中断了线程
     */
    public static boolean interruptThreadByName(String threadNameContains) {
        // 获取线程池中的工作线程
        Set<Thread> threads = getActiveThreads();

        boolean interrupted = false;
        for (Thread thread : threads) {
            if (thread.getName().contains(threadNameContains)) {
                thread.interrupt();
                interrupted = true;
            }
        }
        //TODO: 从Map中删除信息
        return interrupted;
    }

    /**
     * 获取线程池中所有活动线程
     */
    private static Set<Thread> getActiveThreads() {
        Set<Thread> threads = new HashSet<>();

        try {
            // 使用反射获取线程池中的worker集合
            Field workersField = ThreadPoolExecutor.class.getDeclaredField("workers");
            workersField.setAccessible(true);
            @SuppressWarnings("unchecked")
            HashSet<SyncFinisher.Worker> workers = (HashSet<SyncFinisher.Worker>) workersField.get(poolExecutor);

            // 获取每个worker中的线程
            Field threadField = SyncFinisher.Worker.class.getDeclaredField("thread");
            threadField.setAccessible(true);

            for (SyncFinisher.Worker worker : workers) {
                threads.add((Thread) threadField.get(worker));
            }
        } catch (Exception e) {
            // 反射失败时回退到全部线程
            System.err.println("无法通过反射获取线程池线程，使用全部线程集合");
            threads = Thread.getAllStackTraces().keySet();
        }

        return threads;
    }

}
